package tjs.study.notes.dotest.proxy.cglib_eclipse;

import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import tjs.study.notes.dotest.TjsStudyNotesApplication;
import tjs.study.notes.dotest.proxy.service.UserService;

import java.lang.reflect.Method;

/**
 * Created by Nicky.Tang on 2021/9/15 9:53 下午
 *
 * @since 02.12.10
 */
public class DoTest {
	/**
	 * cglib操作字节码的位置
	 * {@link Enhancer#generateClass(org.objectweb.asm.ClassVisitor)}
	 *
	 * @param args
	 */
	public static void main(String[] args) {
		//在指定目录下生成动态代理类，我们可以反编译看一下里面到底是一些什么东西
		System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, TjsStudyNotesApplication.work_space + "/proxy/cglib_eclipse");
		System.out.println(TjsStudyNotesApplication.work_space + "/proxy/cglib_eclipse");
		Enhancer enhancer = new Enhancer();
		//设置目标对象的class
		enhancer.setSuperclass(UserService.class);
		//设置回调函数->切面
		//enhancer.setCallback(new UserServiceProxy());
		enhancer.setCallbacks(new Callback[]{new UserServiceProxy(), new UserServiceProxy2()});
		enhancer.setCallbackFilter((method)->{
			if(method.getName().equals("logout")){
				return 1;
			}else {
				return 0;
			}
		});

		//创建代理类EnableTransactionManagement
		UserService proxyDog = (UserService) enhancer.create();
		System.out.println(proxyDog.getClass());//original.UserService$$EnhancerByCGLIB$$47be1c9e

		//调用目标方法
		System.out.println("proxyDog.login>>>>>>>>");
		proxyDog.login();
		proxyDog.logout();
	}



	public static class UserServiceProxy implements MethodInterceptor {
		@Override
		public Object intercept(Object enhancerInstance, Method methodEnhancer, Object[] objects, MethodProxy methodTarget) throws Throwable {
			System.out.println(methodEnhancer.getName() + "前置增强、、、");

			//Object res = methodEnhancer.invoke(enhancerInstance, objects);
			// Object res = methodEnhancer.invoke(enhancerInstance, objects);//调用代理后的class的login方法 -> 又会再次回到当前切面 进入死循环
			// Object res = methodTarget.invoke(enhancerInstance, objects);//调用代理后的class的login方法 -> 又会再次回到当前切面 进入死循环
			Object res = methodTarget.invokeSuper(enhancerInstance, objects);//调用代理后的class的代理login方法(CGLIB$login$0) -> super.login()

			System.out.println(methodEnhancer.getName() + "后置增强、、、");
			return res;
		}
	}

	public static class UserServiceProxy2 implements MethodInterceptor {
		@Override
		public Object intercept(Object enhancerInstance, Method methodEnhancer, Object[] objects, MethodProxy methodTarget) throws Throwable {
			System.out.println(methodEnhancer.getName() + "前置增强2、、、");

				Object res = methodTarget.invokeSuper(enhancerInstance, objects);

			System.out.println(methodEnhancer.getName() + "后置增强2、、、");
			return res;
		}
	}
}
